package com.baidu.infinity.ui.fragment.home.view

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.RectF
import android.os.Build
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.annotation.RequiresApi
import com.baidu.infinity.ui.fragment.home.shape.shapes.CircleShape
import com.baidu.infinity.ui.fragment.home.shape.LayerManager
import com.baidu.infinity.ui.fragment.home.shape.shapes.ArrowLineShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.BezelShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.CasualShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.EraserShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.LineShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.LocationShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.RectangleShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.TextShape
import com.baidu.infinity.ui.fragment.home.shape.shapes.TriangleShape
import com.baidu.infinity.ui.util.OperationType
import com.baidu.infinity.ui.util.state.ShapeState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import androidx.core.graphics.createBitmap


class DrawView(
    context: Context,
    attrs: AttributeSet?
): View(context,attrs) {
    @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
    private val mLayerManager = LayerManager.instance
    private var mBackgroundBitmap: Bitmap ?= null
    private val rectF: RectF by lazy {
        RectF(0f,0f,width.toFloat(),height.toFloat())
    }
    var setEndPointListener: () -> Unit = {}
    var setKeyboardListener: (state: Boolean) -> Unit = {}
    var mOperationType = OperationType.NONE
    @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mLayerManager.addLayer(measuredWidth,measuredHeight)
    }
    @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if(mBackgroundBitmap != null){
            canvas.drawBitmap(mBackgroundBitmap!!,null,rectF,null)
        }
        mLayerManager.draw()
        mLayerManager.getLayersBitmap().forEach {
            canvas.drawBitmap(it,0f,0f,null)
        }
    }
    @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when(event?.action){
            MotionEvent.ACTION_DOWN ->{
                if (mOperationType.ordinal in 2..11){
                    when(mOperationType){
                        OperationType.DRAW_CIRCLE ->{
                            val circleShape = CircleShape()
                            circleShape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(CircleShape(),event.x,event.y)
                        }
                        OperationType.DRAW_RECTANGLE ->{
                            val shape = RectangleShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                        }
                        OperationType.DRAW_LINE ->{
                            val shape = LineShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                        }
                        OperationType.DRAW_CURVE ->{
                            val shape = CasualShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                        }
                        OperationType.DRAW_TRIANGLE ->{
                            val shape = TriangleShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                        }
                        OperationType.DRAW_BEZEL ->{
                            val shape = BezelShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                        }
                        OperationType.DRAW_LINE_ARROW ->{
                            val shape = ArrowLineShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                        }
                        OperationType.DRAW_LOCATION ->{
                            val shape = LocationShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                        }
                        OperationType.DRAW_TEXT ->{
                            var shape = mLayerManager.getCurrentLayer()?.getCurrentShape()
                            if(shape != null && shape.mState == ShapeState.DRAWING){
                                shape = shape as TextShape
                                setKeyboardListener(false)
                                shape.mTextPaintColor = LayerManager.instance.mColor
                                shape.mState = ShapeState.NORMAL
                                invalidate()
                            }else{
                                val textShape = TextShape()
                                mLayerManager.addShape(textShape,event.x,event.y)
                                setKeyboardListener(true)
                                textShape.mState = ShapeState.DRAWING

                            }
                        }
                        OperationType.DRAW_ERASER ->{
                            val shape = EraserShape()
                            shape.mState = ShapeState.DRAWING
                            mLayerManager.addShape(shape,event.x,event.y)
                            mLayerManager.getCurrentLayer()?.getCurrentShape()?.let {
                                it.updateState()
                            }
                        }
                        else -> {

                        }
                    }

                }
                if(mOperationType == OperationType.DRAW_MOVE){
                    LayerManager.instance.updateSelectedShape(event.x,event.y)
                    invalidate()
                }
                if(mOperationType == OperationType.DRAW_BRUSH){
                    LayerManager.instance.updateSelectedShapeColor(event.x,event.y)
                    invalidate()
                }
                return true
            }
            MotionEvent.ACTION_MOVE ->{
                if(mOperationType == OperationType.DRAW_MOVE){
                    LayerManager.instance.calculateSelectLocation(event.x,event.y)
                    invalidate()
                }
                if (mOperationType.ordinal in 2..11){
                    mLayerManager.setEndPoint(event.x,event.y)
                }

                invalidate()

            }
            MotionEvent.ACTION_UP ->{
                setEndPointListener()
                if(mOperationType != OperationType.DRAW_TEXT){
                    mLayerManager.getCurrentLayer()?.getCurrentShape()?.updateState()
                }
            }
            else ->{}
        }
        return super.onTouchEvent(event)

    }
    fun getCurrentOperationType(): OperationType{
        return mOperationType
    }
    @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
    fun cancelLastShapeEdit(){
        mLayerManager.getCurrentLayer()?.getCurrentShape()?.mState = ShapeState.NORMAL
        invalidate()
    }
    @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
    fun getBitmap():Flow<Bitmap> {
        val bitmapFlow: Flow<Bitmap> = flow {
            val bitmap = createBitmap(width, height)
            val canvas = Canvas(bitmap)
            if (mBackgroundBitmap != null) {
                canvas.drawBitmap(mBackgroundBitmap!!, null, rectF, null)
            }else{
                canvas.drawColor(Color.WHITE)
            }
            mLayerManager.getLayersBitmap().forEach {
                canvas.drawBitmap(it, 0f, 0f, null)
            }
            emit(bitmap)
        }
        return bitmapFlow
    }

    fun reDraw(){
        invalidate()
    }
    fun setBackgroundBitmap(id: Int){
        mBackgroundBitmap = BitmapFactory.decodeResource(resources,id)
        invalidate()
    }
}